{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Learn Keras for Deep Neural Networks\n",
    "## Chapter 2 - Keras in Action"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Getting started with Deep Learning \n",
    "* Models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Dense(10, input_dim=15))\n",
    "model.add(Activation('relu'))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Core Layers \n",
    "* Dense Layer \n",
    "\n",
    "#### Defintion of a Dense Layer\n",
    "\n",
    "keras.layers.Dense(units, activation=None, use_bias=True, \n",
    "                   kernel_initializer='glorot_uniform', \n",
    "                   bias_initializer='zeros', \n",
    "                   kernel_regularizer=None, \n",
    "                   bias_regularizer=None, \n",
    "                   activity_regularizer=None, \n",
    "                   kernel_constraint=None, \n",
    "                   bias_constraint=None)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = Sequential()\n",
    "model.add(Dense(5,input_dim=10, activation = \"sigmoid\"))\n",
    "model.add(Dense(1, activation = \"sigmoid\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Core Layers \n",
    "* Dropout Layer\n",
    "\n",
    "Definition - keras.layers.Dropout(rate, noise_shape=None, seed=None)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.layers import Dropout\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Dense(5,input_dim=10, activation = \"sigmoid\"))\n",
    "model.add(Dropout(rate = 0.1,seed=100))\n",
    "model.add(Dense(1, activation = \"sigmoid\"))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Putting it all together"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Download the data using Keras; this will need an active internet connection\n",
    "from keras.datasets import boston_housing\n",
    "(x_train, y_train), (x_test, y_test) = boston_housing.load_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 6000 samples, validate on 2000 samples\n",
      "Epoch 1/3\n",
      "6000/6000 [==============================] - 2s 273us/step - loss: 0.6932 - acc: 0.5053 - val_loss: 0.6931 - val_acc: 0.5145\n",
      "Epoch 2/3\n",
      "6000/6000 [==============================] - 0s 36us/step - loss: 0.6930 - acc: 0.5073 - val_loss: 0.6930 - val_acc: 0.5135\n",
      "Epoch 3/3\n",
      "6000/6000 [==============================] - 0s 37us/step - loss: 0.6928 - acc: 0.5107 - val_loss: 0.6929 - val_acc: 0.5120\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0xb1e5caf60>"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation\n",
    "\n",
    "\n",
    "from numpy.random import seed\n",
    "seed(2018)\n",
    "from tensorflow import set_random_seed\n",
    "set_random_seed(2018)\n",
    "\n",
    "\n",
    "# Generate dummy training dataset\n",
    "x_train = np.random.random((6000,10))\n",
    "y_train = np.random.randint(2, size=(6000, 1))\n",
    "\n",
    "# Generate dummy validation dataset\n",
    "x_val = np.random.random((2000,10))\n",
    "y_val = np.random.randint(2, size=(2000, 1))\n",
    "\n",
    "# Generate dummy test dataset\n",
    "x_test = np.random.random((2000,10))\n",
    "y_test = np.random.randint(2, size=(2000, 1))\n",
    "\n",
    "#Define the model architecture\n",
    "model = Sequential()\n",
    "model.add(Dense(64, input_dim=10,activation = \"relu\")) #Layer 1\n",
    "model.add(Dense(32,activation = \"relu\"))               #Layer 2\n",
    "model.add(Dense(16,activation = \"relu\"))               #Layer 3\n",
    "model.add(Dense(8,activation = \"relu\"))                #Layer 4\n",
    "model.add(Dense(4,activation = \"relu\"))                #Layer 5\n",
    "model.add(Dense(1,activation = \"sigmoid\"))             #Output Layer\n",
    "\n",
    "#Configure the model\n",
    "model.compile(optimizer='Adam',loss='binary_crossentropy',metrics=['accuracy'])\n",
    "\n",
    "#Train the model\n",
    "model.fit(x_train, y_train, batch_size=64, epochs=3, validation_data=(x_val,y_val))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.88234931 0.10432774 0.90700933 0.3063989  0.44640887 0.58998539\n",
      "  0.8371111  0.69780061 0.80280284 0.10721508]\n",
      " [0.75709253 0.99967101 0.725931   0.14144824 0.3567206  0.94270411\n",
      "  0.61016189 0.22757747 0.66873237 0.69290455]\n",
      " [0.41686251 0.17180956 0.97689051 0.33022414 0.62904415 0.16061095\n",
      "  0.08995264 0.97082236 0.81657757 0.57136573]\n",
      " [0.34585315 0.403744   0.13738304 0.90093449 0.93393613 0.04737714\n",
      "  0.67150688 0.03483186 0.25269136 0.55712505]\n",
      " [0.52582348 0.35296779 0.09298297 0.30450898 0.86242986 0.71693654\n",
      "  0.96407149 0.53970186 0.95053982 0.66798156]\n",
      " [0.87424103 0.48120492 0.13739854 0.69022154 0.50211855 0.07451108\n",
      "  0.52351229 0.91856772 0.5274287  0.36424787]\n",
      " [0.92818629 0.49269142 0.23640703 0.53141538 0.16525533 0.371387\n",
      "  0.74225181 0.23704057 0.39196365 0.05938974]\n",
      " [0.10276893 0.55725012 0.81930231 0.48981038 0.90230697 0.49004436\n",
      "  0.00303589 0.84366215 0.54368872 0.13869147]\n",
      " [0.08572875 0.40161209 0.82697863 0.80616256 0.20954603 0.30218791\n",
      "  0.75345933 0.12518232 0.88233405 0.93448737]\n",
      " [0.142472   0.18949702 0.40460224 0.473948   0.09906794 0.47471235\n",
      "  0.84469429 0.79187259 0.35902305 0.74563608]]\n",
      "sdf\n",
      "[[0.26794846 0.45311343 0.3163587  0.40551464 0.83324812 0.29926402\n",
      "  0.58604988 0.4265123  0.39054642 0.11719099]\n",
      " [0.38835659 0.13661398 0.43791187 0.35953925 0.28232502 0.63733196\n",
      "  0.04315783 0.36698055 0.96092323 0.07970832]\n",
      " [0.78676828 0.4734678  0.78487578 0.55263435 0.57265221 0.79656561\n",
      "  0.98978979 0.9059708  0.85610936 0.4178593 ]\n",
      " [0.13634476 0.01439594 0.63673535 0.31518873 0.26061521 0.41831776\n",
      "  0.83293788 0.03042154 0.89161667 0.12073609]\n",
      " [0.74403628 0.34219727 0.81769273 0.11254841 0.00920876 0.36165523\n",
      "  0.50033997 0.84242664 0.40227329 0.06407224]\n",
      " [0.50533902 0.50701475 0.54050708 0.59235759 0.97741647 0.06884431\n",
      "  0.13387683 0.17632566 0.61302174 0.5997502 ]\n",
      " [0.57084323 0.93229789 0.88993136 0.77996226 0.70914402 0.60017046\n",
      "  0.56650348 0.9040863  0.28178547 0.09585478]\n",
      " [0.76576207 0.61956373 0.47285659 0.62899629 0.01747167 0.12566464\n",
      "  0.12694226 0.31119618 0.08738258 0.36606282]\n",
      " [0.56215208 0.68463042 0.18359825 0.43401489 0.42432408 0.56262951\n",
      "  0.16307223 0.73921326 0.12070907 0.0267515 ]\n",
      " [0.89407057 0.1028051  0.63743563 0.72838004 0.9416155  0.979424\n",
      "  0.05262605 0.19090817 0.74782467 0.13233449]]\n"
     ]
    }
   ],
   "source": [
    "print(x_train[:10])\n",
    "print(\"sdf\")\n",
    "print(x_val[:10])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type of the Dataset: <class 'numpy.ndarray'>\n",
      "Shape of training data : (404, 13)\n",
      "Shape of training labels : (404,)\n",
      "Shape of testing data : <class 'numpy.ndarray'>\n",
      "Shape of testing labels : (102,)\n"
     ]
    }
   ],
   "source": [
    "#Explore the data structure using basic python commands\n",
    "print(\"Type of the Dataset:\",type(y_train))\n",
    "print(\"Shape of training data :\",x_train.shape)\n",
    "print(\"Shape of training labels :\",y_train.shape)\n",
    "print(\"Shape of testing data :\",type(x_test))\n",
    "print(\"Shape of testing labels :\",y_test.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Metadata for the data\n",
    "\n",
    "| Column Name \t| Description                                                           \t|\n",
    "|-------------\t|-----------------------------------------------------------------------\t|\n",
    "| CRIM        \t| per capita crime rate by town                                         \t|\n",
    "| ZN          \t| proportion of residential land zoned for lots over 25,000 sq.ft.      \t|\n",
    "| INDUS       \t| proportion of non-retail business acres per town                      \t|\n",
    "| CHAS        \t| Charles River dummy variable (= 1 if tract bounds river; 0 otherwise) \t|\n",
    "| NOX         \t| nitric oxides concentration (parts per 10 million)                    \t|\n",
    "| RM          \t| average number of rooms per dwelling                                  \t|\n",
    "| AGE         \t| proportion of owner-occupied units built prior to 1940                \t|\n",
    "| DIS         \t| weighted distances to five Boston employment centers                  \t|\n",
    "| RAD         \t| index of accessibility to radial highways                             \t|\n",
    "| TAX         \t| full-value property-tax rate per USD 10,000                              \t|\n",
    "| PTRATIO     \t| pupil-teacher ratio by town                                           \t|\n",
    "| B           \t| 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town        \t|\n",
    "| LSTAT       \t| Percent lower status of the population                                \t|\n",
    "| MEDV        \t| Median value of owner-occupied homes in USD 1000's                       \t|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.23247e+00, 0.00000e+00, 8.14000e+00, 0.00000e+00, 5.38000e-01,\n",
       "        6.14200e+00, 9.17000e+01, 3.97690e+00, 4.00000e+00, 3.07000e+02,\n",
       "        2.10000e+01, 3.96900e+02, 1.87200e+01],\n",
       "       [2.17700e-02, 8.25000e+01, 2.03000e+00, 0.00000e+00, 4.15000e-01,\n",
       "        7.61000e+00, 1.57000e+01, 6.27000e+00, 2.00000e+00, 3.48000e+02,\n",
       "        1.47000e+01, 3.95380e+02, 3.11000e+00],\n",
       "       [4.89822e+00, 0.00000e+00, 1.81000e+01, 0.00000e+00, 6.31000e-01,\n",
       "        4.97000e+00, 1.00000e+02, 1.33250e+00, 2.40000e+01, 6.66000e+02,\n",
       "        2.02000e+01, 3.75520e+02, 3.26000e+00]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_train[:3,:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Desing the neural network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 404 samples, validate on 104 samples\n",
      "Epoch 1/3\n",
      "404/404 [==============================] - 0s 619us/step - loss: 586.9058 - mean_absolute_percentage_error: 100.2173 - val_loss: 679.5489 - val_mean_absolute_percentage_error: 99.8676\n",
      "Epoch 2/3\n",
      "404/404 [==============================] - 0s 38us/step - loss: 580.3056 - mean_absolute_percentage_error: 99.3194 - val_loss: 668.7341 - val_mean_absolute_percentage_error: 98.5805\n",
      "Epoch 3/3\n",
      "404/404 [==============================] - 0s 52us/step - loss: 563.9453 - mean_absolute_percentage_error: 97.0106 - val_loss: 637.4159 - val_mean_absolute_percentage_error: 95.0793\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0xb207ab3c8>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Activation\n",
    "\n",
    "#Extract the last 100 rows from the training data to create the validation datasets.\n",
    "x_val = x_train[300:,]\n",
    "y_val = y_train[300:,]\n",
    "\n",
    "#Define the model architecture\n",
    "model = Sequential()\n",
    "model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu'))\n",
    "model.add(Dense(6, kernel_initializer='normal', activation='relu'))\n",
    "model.add(Dense(1, kernel_initializer='normal'))\n",
    "\n",
    "# Compile model\n",
    "model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mean_absolute_percentage_error'])\n",
    "\n",
    "#Train the model\n",
    "model.fit(x_train, y_train, batch_size=32, epochs=3, validation_data=(x_val,y_val))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "102/102 [==============================] - 0s 47us/step\n",
      "loss  :  60.73957645191866\n",
      "mean_absolute_percentage_error  :  30.230230032228956\n"
     ]
    }
   ],
   "source": [
    "results = model.evaluate(x_test, y_test)\n",
    "\n",
    "for i in range(len(model.metrics_names)):\n",
    "    print(model.metrics_names[i],\" : \", results[i])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 404 samples, validate on 104 samples\n",
      "Epoch 1/30\n",
      "404/404 [==============================] - 0s 38us/step - loss: 56.0712 - mean_absolute_percentage_error: 23.3996 - val_loss: 81.3938 - val_mean_absolute_percentage_error: 22.2527\n",
      "Epoch 2/30\n",
      "404/404 [==============================] - 0s 36us/step - loss: 54.9494 - mean_absolute_percentage_error: 23.8799 - val_loss: 76.7879 - val_mean_absolute_percentage_error: 24.4968\n",
      "Epoch 3/30\n",
      "404/404 [==============================] - 0s 50us/step - loss: 55.3270 - mean_absolute_percentage_error: 25.9749 - val_loss: 78.1830 - val_mean_absolute_percentage_error: 23.0118\n",
      "Epoch 4/30\n",
      "404/404 [==============================] - 0s 64us/step - loss: 54.4114 - mean_absolute_percentage_error: 23.7856 - val_loss: 77.4965 - val_mean_absolute_percentage_error: 23.0605\n",
      "Epoch 5/30\n",
      "404/404 [==============================] - 0s 54us/step - loss: 54.0004 - mean_absolute_percentage_error: 24.2953 - val_loss: 77.0992 - val_mean_absolute_percentage_error: 22.9819\n",
      "Epoch 6/30\n",
      "404/404 [==============================] - 0s 57us/step - loss: 53.7771 - mean_absolute_percentage_error: 24.1350 - val_loss: 76.5673 - val_mean_absolute_percentage_error: 22.9386\n",
      "Epoch 7/30\n",
      "404/404 [==============================] - 0s 32us/step - loss: 53.2988 - mean_absolute_percentage_error: 23.4371 - val_loss: 76.6129 - val_mean_absolute_percentage_error: 22.6209\n",
      "Epoch 8/30\n",
      "404/404 [==============================] - 0s 49us/step - loss: 53.1344 - mean_absolute_percentage_error: 23.8508 - val_loss: 75.0798 - val_mean_absolute_percentage_error: 23.3396\n",
      "Epoch 9/30\n",
      "404/404 [==============================] - 0s 46us/step - loss: 52.8575 - mean_absolute_percentage_error: 23.9303 - val_loss: 76.7351 - val_mean_absolute_percentage_error: 22.0030\n",
      "Epoch 10/30\n",
      "404/404 [==============================] - 0s 43us/step - loss: 52.5260 - mean_absolute_percentage_error: 22.9515 - val_loss: 74.3610 - val_mean_absolute_percentage_error: 22.9795\n",
      "Epoch 11/30\n",
      "404/404 [==============================] - 0s 57us/step - loss: 52.2489 - mean_absolute_percentage_error: 24.6278 - val_loss: 74.1006 - val_mean_absolute_percentage_error: 22.8175\n",
      "Epoch 12/30\n",
      "404/404 [==============================] - 0s 28us/step - loss: 52.0432 - mean_absolute_percentage_error: 22.5138 - val_loss: 75.2133 - val_mean_absolute_percentage_error: 21.8098\n",
      "Epoch 13/30\n",
      "404/404 [==============================] - 0s 45us/step - loss: 51.3897 - mean_absolute_percentage_error: 23.2307 - val_loss: 73.4567 - val_mean_absolute_percentage_error: 22.3941\n",
      "Epoch 14/30\n",
      "404/404 [==============================] - 0s 31us/step - loss: 51.3470 - mean_absolute_percentage_error: 24.8982 - val_loss: 72.8103 - val_mean_absolute_percentage_error: 22.2180\n",
      "Epoch 15/30\n",
      "404/404 [==============================] - 0s 56us/step - loss: 50.7736 - mean_absolute_percentage_error: 21.7647 - val_loss: 73.3813 - val_mean_absolute_percentage_error: 21.4604\n",
      "Epoch 16/30\n",
      "404/404 [==============================] - 0s 43us/step - loss: 49.8907 - mean_absolute_percentage_error: 23.6661 - val_loss: 70.6683 - val_mean_absolute_percentage_error: 23.0048\n",
      "Epoch 17/30\n",
      "404/404 [==============================] - 0s 48us/step - loss: 49.8264 - mean_absolute_percentage_error: 23.6251 - val_loss: 70.8511 - val_mean_absolute_percentage_error: 22.3011\n",
      "Epoch 18/30\n",
      "404/404 [==============================] - 0s 38us/step - loss: 49.3035 - mean_absolute_percentage_error: 22.1989 - val_loss: 71.4762 - val_mean_absolute_percentage_error: 21.3470\n",
      "Epoch 19/30\n",
      "404/404 [==============================] - 0s 47us/step - loss: 48.6826 - mean_absolute_percentage_error: 22.2847 - val_loss: 69.0820 - val_mean_absolute_percentage_error: 22.6076\n",
      "Epoch 20/30\n",
      "404/404 [==============================] - 0s 39us/step - loss: 48.7499 - mean_absolute_percentage_error: 24.0462 - val_loss: 69.9161 - val_mean_absolute_percentage_error: 21.2971\n",
      "Epoch 21/30\n",
      "404/404 [==============================] - 0s 38us/step - loss: 48.1568 - mean_absolute_percentage_error: 20.9823 - val_loss: 68.5259 - val_mean_absolute_percentage_error: 21.6884\n",
      "Epoch 22/30\n",
      "404/404 [==============================] - 0s 50us/step - loss: 48.4463 - mean_absolute_percentage_error: 25.0588 - val_loss: 67.1394 - val_mean_absolute_percentage_error: 22.0329\n",
      "Epoch 23/30\n",
      "404/404 [==============================] - 0s 34us/step - loss: 48.4314 - mean_absolute_percentage_error: 20.3513 - val_loss: 67.9163 - val_mean_absolute_percentage_error: 20.9677\n",
      "Epoch 24/30\n",
      "404/404 [==============================] - 0s 46us/step - loss: 46.2969 - mean_absolute_percentage_error: 22.1445 - val_loss: 65.6267 - val_mean_absolute_percentage_error: 22.2411\n",
      "Epoch 25/30\n",
      "404/404 [==============================] - 0s 38us/step - loss: 46.3643 - mean_absolute_percentage_error: 23.5520 - val_loss: 67.3056 - val_mean_absolute_percentage_error: 20.3864\n",
      "Epoch 26/30\n",
      "404/404 [==============================] - 0s 45us/step - loss: 46.0554 - mean_absolute_percentage_error: 20.8538 - val_loss: 65.1951 - val_mean_absolute_percentage_error: 21.1404\n",
      "Epoch 27/30\n",
      "404/404 [==============================] - 0s 39us/step - loss: 45.1127 - mean_absolute_percentage_error: 21.9770 - val_loss: 64.4997 - val_mean_absolute_percentage_error: 21.0543\n",
      "Epoch 28/30\n",
      "404/404 [==============================] - 0s 42us/step - loss: 44.8834 - mean_absolute_percentage_error: 21.9936 - val_loss: 64.7258 - val_mean_absolute_percentage_error: 20.4036\n",
      "Epoch 29/30\n",
      "404/404 [==============================] - 0s 44us/step - loss: 44.5773 - mean_absolute_percentage_error: 20.6821 - val_loss: 63.3499 - val_mean_absolute_percentage_error: 20.7962\n",
      "Epoch 30/30\n",
      "404/404 [==============================] - 0s 41us/step - loss: 44.2133 - mean_absolute_percentage_error: 21.3362 - val_loss: 63.1252 - val_mean_absolute_percentage_error: 20.4065\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0xb20bd45c0>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Train the model\n",
    "model.fit(x_train, y_train, batch_size=32, epochs=30, validation_data=(x_val,y_val))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "102/102 [==============================] - 0s 43us/step\n",
      "loss  :  49.132040584788605\n",
      "mean_absolute_percentage_error  :  25.194283765905045\n"
     ]
    }
   ],
   "source": [
    "results = model.evaluate(x_test, y_test)\n",
    "\n",
    "for i in range(len(model.metrics_names)):\n",
    "    print(model.metrics_names[i],\" : \", results[i])\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
